package controller;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import model.AppModel;
import model.Email;
import model.EmailBuilder;
import model.Filter;
import model.ModelException;

public class ServerConnector implements Runnable {

	private AppModel model;
	private AppController appController;
	private ObjectInputStream serverReader;
	private String ip;
	private Integer port;

	/**
	 * Constructor
	 * 
	 * @param appController
	 * @param model
	 */
	public ServerConnector(AppController appController, AppModel model) {
		this.serverReader = null;
		this.model = model;
		this.appController = appController;
	}

	@Override
	public void run() {

		HashMap<String, String> serverProps = model.getServerProperties();
		ip = serverProps.get("ip");
		port = Integer.valueOf(serverProps.get("port"));
		try {
			connect();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Connects to the server
	 * 
	 * @param ip
	 * @param port
	 * @throws InterruptedException
	 */
	private void connect() throws InterruptedException {

		System.out.println("Trying to connect to " + ip + ":" + port + "...");

		try {
			
			model.serverSocket = new Socket(ip, port);
			model.setStreams();
			
			System.out.println("Yay! Connected to server, sending name...");

			
			
			
			// Send the name to the server
//			model.getOsStream() new ObjectOutputStream(
//					model.serverSocket.getOutputStream());
			model.getOsStream().writeObject(new String(model.getUser().getName()));

			// Now start listening from server
			startListening();

		} catch (UnknownHostException e) {
			System.out.println("Could not connect, retrying in 5 secs");
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			connect();
		} catch (IOException e) {
			System.out.println("Could not connect, retrying in 5 secs");
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			connect();
		}
	}

	/**
	 * Keep listening from server
	 */
	private void startListening() throws InterruptedException {

		System.out.println("Started listening..");

			serverReader = model.getInStream();
	

		String message = null;

		while (true) {

			System.out.println("Waiting for message from server...");

			try {
				message = (String) serverReader.readObject();
				System.out.println("Got this message from server:" + message);
				
				handleMessage(message);
				
				
			} catch (ClassNotFoundException e) {
				System.out.println("recieved a non string");
			} catch (IOException e) {
				Thread.sleep(5000);
				connect();
			}
		}
	}

	/**
	 * Handles the message that just came
	 * 
	 * @param message
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	private void handleMessage(String message) throws ClassNotFoundException,
			IOException {

		switch (message) {

			case "emails": {
				actionAddNewEmails((ArrayList<Email>) serverReader.readObject());
				break;
			}
	
			default: {
				System.out.println("Unknown message!!!");
			}

		}
	}

	/**
	 * Adds the newly arrived emails
	 * 
	 * @param readObject
	 */
	synchronized private void actionAddNewEmails(ArrayList<Email> emails) {

		// Email em1, em2, em3,em4;
		// EmailBuilder emBuilder = new EmailBuilder();
		// Date date = new Date();
		// Timestamp currentTime = (new Timestamp(date.getTime()));
		//
		// emBuilder = new EmailBuilder();
		// em1 = emBuilder.setTo("Sara@gmail.com")
		// .setFrom("Buthainah.aldosary@gmail.com").setSubject("Hello")
		// .setBody("Just dropping by to say hello").setRead(false)
		// .setTimestamp(currentTime).setFolderId(-1).build();
		//
		// em2 = emBuilder.setTo("Musab@gmail.com")
		// .setFrom("Buthainah.aldosary@gmail.com").setSubject("Hello")
		// .setBody("Project in progress").setRead(false)
		// .setTimestamp(currentTime).setFolderId(-1).build();
		//
		// em3 = emBuilder.setTo("Sukhjinder@gmail.com")
		// .setFrom("Buthainah.aldosary@gmail.com").setSubject("Hello")
		// .setBody("How are you?").setRead(false)
		// .setTimestamp(currentTime).setFolderId(-1).build();
		//
		// em4 = emBuilder.setTo("Sara@gmail.com")
		// .setFrom("Buthainah.aldosary@gmail.com").setSubject("Hello")
		// .setBody("How are you?").setRead(false)
		// .setTimestamp(currentTime).setFolderId(-1).build();
		//
		// ArrayList<Email> emails = new ArrayList<Email>();
		//
		// emails.add(em1);
		// emails.add(em2);
		// emails.add(em3);
		// emails.add(em4);

		int currentWeight = 0;
		Filter filterToApply = null;

		for (Email em : emails) {
			int maxWeight = 0;
			for (Filter filter : model.getUser().getFilters()) {
				if (filter.filterApplies(em)) {
					currentWeight = filter.getWeight();
					if (currentWeight > maxWeight) {
						maxWeight = currentWeight;
						filterToApply = filter;
					}
				}
			}

			if (filterToApply == null)
				em.setFolderId(model.getUser().getFolder("Inbox").getId());
			else {
				em.setFolderId(filterToApply.getFolderId());
			}
			
			try {	
				em.save();
				model.getUser().getFolder(em.getFolderId()).getEmails().add(em);
			} catch (ModelException e) {
				System.out.println("Could not save the email");
			}
		}
		appController.getNavigationController().refreshNavigationFolders();
	}
}
